﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TestDomainModel;
using MyUtils;

namespace LightPersistTests
{
	[TestClass]
	public class CacheIsWeakReferenced : ContextTestsBase
	{
		[TestMethod]
		public void Should_collect_unused_cache_items()
		{
			var item = Context.Create<FakeControl>();
			Root.Children.Add(item);
			item.Width = 100;

			ChangeTransaction();

			Assert.AreEqual(item, Root.Children[1]);

			ChangeTransaction();

			Assert.AreEqual(item, Root.Children[1]);

			ScrollDownUndoHistory();

			var wr = new WeakReference(item);
			item = null;
			CollectGarbage();

			Assert.IsFalse(wr.IsAlive, "Object should be collected");
		}

		void ScrollDownUndoHistory()
		{
			ScrollDownUndoHistory(200);
		}

		void ScrollDownUndoHistory(int items)
		{
			// perform simple actions to scroll down undo history
			for(var i = 0; i < items; i++)
			{
				child.Width = i;
				ChangeTransaction();
			}
		}

		[DllImport("Psapi.dll")]
		static extern bool EmptyWorkingSet(IntPtr hProcess);

		static void CollectGarbage()
		{
			GC.Collect();
			GC.WaitForPendingFinalizers();
			GC.Collect();
			EmptyWorkingSet(Process.GetCurrentProcess().Handle);
		}

		[TestMethod]
		public void Should_clear_died_cache_entries()
		{
			var item = Context.Create<FakeControl>();
			var id = item.ID;
			Root.Children.Add(item);
			ChangeTransaction();

			Assert.IsTrue((bool)Context.Reflect("cache.cache.containskey", id));

			item = null;

			ScrollDownUndoHistory();
			CollectGarbage();
			for(int i = 0; i < 1050; i++)
			{
				Context.GetObjectByID<FakeRoot>(RootGuid);
			}

			Assert.IsFalse((bool)Context.Reflect("cache.cache.containskey", id));
		}

	}
}
